package com.cy.pj.goods.pojo.dao;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据访问层(持久层)对象的具体实现，在实现类中借助JDBC技术直接访问数据库
 * @Repository 是spring框架中定义一个描述数据层bean对象的注解
 */
@Repository
public class DefaultGoodsDao implements GoodsDao{
    @Autowired
    private DataSource dataSource;

    //初始化一个日志对象
    //在哪个类创建日志对象，我们的getLogger方法内部的对象就为哪个类的字节码对象
    private static final Logger log = LoggerFactory.getLogger(DefaultGoodsDao.class);

    Map<String, Object> rowMap(ResultSetMetaData rsmd, ResultSet rs) throws SQLException {
        Map<String,Object> map = new HashMap<>();
        for (int i=1;i<=rsmd.getColumnCount();i++){
            map.put(rsmd.getColumnName(i), rs.getObject(rsmd.getColumnName(i)));
        }
        return map;
    }

    public void close(ResultSet rs,Statement stmt,Connection conn){
        if(rs!=null)try{rs.close();}catch(Exception e){e.printStackTrace();}
        if(stmt!=null)try{stmt.close();}catch(Exception e){e.printStackTrace();}
        //这里的连接是返回到了池中
        if(conn!=null)try{conn.close();}catch(Exception e){e.printStackTrace();}
    }
    @Override
    public List<Map<String, Object>> findGoods(){
        Connection conn = null;
        Statement stat = null;
        ResultSet res = null;
        List<Map<String,Object>> list = new ArrayList<>();
        try {
            //1.获取连接
            conn = dataSource.getConnection();
            //2.创建statement
            stat = conn.createStatement();
            //3.发送sql
            String sql = "select * from tb_goods";
            res = stat.executeQuery(sql);
            //4.处理结果
            ResultSetMetaData resmd = res.getMetaData();//获取结果集中的元数据(描述数据的数据)
            while (res.next()){
                Map<String,Object> map = new HashMap<>();
//                map.put("id", res.getInt("id"));
//                map.put("name", res.getString("name"));
//                map.put("remark", res.getString("remark"));
//                map.put("createdTime", res.getTimestamp("createdTime"));
//                list.add(map);

                //映射方案2
                list.add(rowMap(resmd,res));
            }
            return list;
        }catch (Exception e){
            //记录日志(一般异常日志借助log.error方法进行记录)
            //log.info("查询异常,{}",e.getMessage());//{}表示占位符
            log.error("查询异常,{}",e.getMessage());
            //e.printStackTrace();
            return null;
        }finally {
            //5.释放资源
//            if(res!=null)try{res.close();}catch(Exception e){e.printStackTrace();}
//            if(stat!=null)try{stat.close();}catch(Exception e){e.printStackTrace();}
//            //这里的连接是返回到了池中
//            if(conn!=null)try{conn.close();}catch(Exception e){e.printStackTrace();}
            close(res, stat,conn );
        }
    }
}

/**
 *对于如上查询商品数据的过程有什么优缺点?
 * 优点:
 * 1)代码简单(就是一些流水代码-步骤固定)
 * 2)使用了连接池，优化了建立连接的过程，从池中获取连接，提高了数据访问性能
 * 3)使用了map做映射，简化了POJO对象定义
 * 缺点:
 * 1)可重用性比较差(例如资源释放代码)
 * 2)行映射不够灵活，过于僵硬(把一行映射到内存中的一个对象)
 * 3)异常的处理不能简单打印一下，然后返回一个null就可以了
 * 4)Map封装数据时值的类型不可控(建议后续修改为POJO对象)
 * 5)对共性模板应该进行封装，特性代码进行提取
 */